import { PureComponent } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { computeOldLineNumber, computeNewLineNumber } from './utils';
import { changePropType, eventsPropType, classNamesPropType } from './propTypes';
import { createEventsBindingSelector } from './selectors';
import CodeCell from './CodeCellWithGram';
import './Change.css';
import utils from 'utils';

export default class UnifiedChange extends PureComponent {
  bindGutterEvents = createEventsBindingSelector();

  bindCodeEvents = createEventsBindingSelector();

  static propTypes = {
    change: changePropType.isRequired,
    selected: PropTypes.bool.isRequired,
    customEvents: eventsPropType,
    customClassNames: classNamesPropType,
    onRenderCode: PropTypes.func,
  };

  static defaultProps = {
    customEvents: {},
    onRenderCode() {},
  };

  componentDidMount() {
    const { change, onRenderCode } = this.props;
    const cell = this.container.querySelector('.diff-code');
    onRenderCode(cell, change);
  }

  componentDidUpdate() {
    // TODO: 如何判断一个td里的代码是不是已经高亮过了？
  }

  render() {
    const {
      change,
      selected,
      customClassNames,
      customEvents,
      gutterAnchor,
      generateAnchorID,
      generateChangeID,
      onRenderCode,
      genWatermarkimage,
    } = this.props;
    const { type, content: originalContent } = change;
    const oldLine = computeOldLineNumber(change);
    const oldLineNumber = oldLine === -1 ? undefined : oldLine;
    const newLine = computeNewLineNumber(change);
    const newLineNumber = newLine === -1 ? undefined : newLine;

    // 以 $BLOB_EXPANDED$ 结尾的行为展开行的标识
    const isExpanded = originalContent.indexOf('$BLOB_EXPANDED$') !== -1;

    // 如果是展开的行，去掉结尾的标识
    let content;
    if (isExpanded) {
      content = originalContent.replace('$BLOB_EXPANDED$', '');
    } else {
      content = originalContent;
    }

    // 如果是展开的行，使用 diff-line-expanded 颜色
    let lineTypeClassName;
    if (isExpanded) {
      lineTypeClassName = utils.isGenWatermarkimage(genWatermarkimage)
        ? 'diff-line-expanded diff-line-expanded-wartimage'
        : 'diff-line-expanded';
    } else {
      lineTypeClassName = 'diff-line-normal';
    }

    const boundGutterEvents = this.bindGutterEvents(customEvents.gutter, change);
    const boundCodeEvents = this.bindCodeEvents(customEvents.code, change);

    const anchorID = generateAnchorID(change);
    const changeID = generateChangeID ? generateChangeID(change) : '';
    const gutterClassName = classNames(
      'diff-gutter',
      `diff-gutter-${type}`,
      customClassNames.gutter,
      { 'diff-gutter-selected': selected },
      { 'diff-code-image': `${type}` === 'insert' && utils.isGenWatermarkimage(genWatermarkimage) },
      {
        'diff-code-delet-image':
          `${type}` === 'delete' && utils.isGenWatermarkimage(genWatermarkimage),
      },
      {
        'diff-code-gutter-normal-image':
          `${type}` === 'normal' && utils.isGenWatermarkimage(genWatermarkimage),
      },
    );
    const codeClassName = classNames(
      'diff-code',
      `diff-code-${type}`,
      customClassNames.code,
      { 'diff-code-selected': selected },
      { 'diff-code-image': `${type}` === 'insert' && utils.isGenWatermarkimage(genWatermarkimage) },
      {
        'diff-code-delet-image':
          `${type}` === 'delete' && utils.isGenWatermarkimage(genWatermarkimage),
      },
      {
        'diff-code-gutter-normal-image':
          `${type}` === 'normal' && utils.isGenWatermarkimage(genWatermarkimage),
      },
    );
    const codeProps = {
      className: codeClassName,
      onRender: onRenderCode,
      'data-line-number': `${change.oldLineNumber}-${change.newLineNumber}`,
      // 标记是否删除行
      isDelete: type === 'delete' ? '1' : '0',
      side: type === 'delete' ? 'left' : 'right',
      id: changeID,
      ...boundCodeEvents,
    };

    return (
      <tr
        id={anchorID}
        className={classNames('diff-line', customClassNames.line, lineTypeClassName)}
        ref={(container) => {
          this.container = container;
        }}
      >
        <td className={gutterClassName} data-line-number={oldLineNumber} {...boundGutterEvents}>
          {gutterAnchor ? <a href={`#${anchorID}`} data-line-number={oldLineNumber} /> : null}
        </td>
        <td className={gutterClassName} data-line-number={newLineNumber} {...boundGutterEvents}>
          {gutterAnchor ? <a href={`#${anchorID}`} data-line-number={newLineNumber} /> : null}
        </td>
        <CodeCell {...codeProps} text={content} />
      </tr>
    );
  }
}
